﻿using System;
using System.Text;
using System.Text.RegularExpressions;

namespace POP.Mime.Decode
{
	// Utility class for dealing with encoded word strings
	internal static class EncodedWord
	{
		public static string Decode(string encodedWords)
		{
			if(encodedWords == null)
				throw new ArgumentNullException("encodedWords");

			const string encodedWordRegex = @"\=\?(?<Charset>\S+?)\?(?<Encoding>\w)\?(?<Content>.+?)\?\=";
			const string replaceRegex = @"(?<first>" + encodedWordRegex + @")\s+(?<second>" + encodedWordRegex + ")";
			encodedWords = Regex.Replace(encodedWords, replaceRegex, "${first}${second}");
			encodedWords = Regex.Replace(encodedWords, replaceRegex, "${first}${second}");

			string decodedWords = encodedWords;

			MatchCollection matches = Regex.Matches(encodedWords, encodedWordRegex);
			foreach (Match match in matches)
			{
				// If this match was not a success, we should not use it
				if (!match.Success) continue;

				string fullMatchValue = match.Value;

				string encodedText = match.Groups["Content"].Value;
				string encoding = match.Groups["Encoding"].Value;
				string charset = match.Groups["Charset"].Value;

				// Get the encoding which corrosponds to the character set
				Encoding charsetEncoding = EncodingFinder.FindEncoding(charset);

				// Store decoded text here when done
				string decodedText;

				// Encoding may also be written in lowercase
				switch (encoding.ToUpperInvariant())
				{
					case "B":
						decodedText = Base64.Decode(encodedText, charsetEncoding);
						break;
					case "Q":
						decodedText = QuotedPrintable.DecodeEncodedWord(encodedText, charsetEncoding);
						break;

					default:
						throw new ArgumentException("The encoding " + encoding + " was not recognized");
				}

				// Repalce our encoded value with our decoded value
				decodedWords = decodedWords.Replace(fullMatchValue, decodedText);
			}

			return decodedWords;
		}
	}
}